﻿// ----------------------------------------------------------------------------------
// <copyright file="SimpleIocContainer.cs" company="Christopher Hines">
// Copyright (c) 2012 All Right Reserved
// </copyright>
// <author>Chris Hines</author>
// <date>2012-02-16</date>
// <summary>
//     Configurable context-based instance container
// </summary>
// ----------------------------------------------------------------------------------

namespace Copperfield.Sdk
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// Configurable context-based instance container
    /// </summary>
    public static class SimpleIocContainer
    {
        /// <summary>
        /// Gets the instance dictionary
        /// </summary>
        /// <value>
        /// The instance dictionary
        /// </value>
        private static readonly Dictionary<Type, object> instanceDictionary = new Dictionary<Type, object>();

        /// <summary>
        /// Gets the override dictionary
        /// </summary>
        /// <value>
        /// The override dictionary
        /// </value>
        private static readonly Dictionary<Type, Func<object>> overrideDictionary = new Dictionary<Type, Func<object>>();

        /// <summary>
        /// Gets an instance of the type
        /// </summary>
        /// <param name="type">The instance type</param>
        /// <returns>An instance of the type</returns>
        public static object GetInstance(Type type)
        {
            if (overrideDictionary.ContainsKey(type))
            {
                return overrideDictionary[type]();
            }

            return instanceDictionary.ContainsKey(type) ? instanceDictionary[type] : null;
        }

        /// <summary>
        /// Gets an instance of the type
        /// </summary>
        /// <typeparam name="T">The instance type</typeparam>
        /// <returns>An instance of the type</returns>
        public static T GetInstance<T>()
        {
            if (overrideDictionary.ContainsKey(typeof(T)))
            {
                var obj = overrideDictionary[typeof(T)]();

                return obj is T ? (T)obj : default(T);
            }
            else
            {
                if (!instanceDictionary.ContainsKey(typeof(T)))
                {
                    return default(T);
                }

                var obj = instanceDictionary[typeof(T)];

                return obj is T ? (T)obj : default(T);
            }
        }

        /// <summary>
        /// Configures the instance of the plugin type
        /// </summary>
        /// <typeparam name="T">The plugin type</typeparam>
        /// <returns>A new configuration expresion</returns>
        public static SimpleContainerExpression<T> For<T>()
        {
            return new SimpleContainerExpression<T>();
        }

        /// <summary>
        /// Adds a retrieval override for for the specified plugin
        /// </summary>
        /// <param name="type">The plugin type</param>
        /// <param name="func">The retrieval delegate</param>
        public static void DefineRetrievalOverride(Type type, Func<object> func)
        {
            if (overrideDictionary.ContainsKey(type))
            {
                overrideDictionary[type] = func;
            }
            else
            {
                overrideDictionary.Add(type, func);
            }
        }

        /// <summary>
        /// Configures an instance of a plugin type
        /// </summary>
        /// <param name="type">The plugin type</param>
        /// <param name="obj">The plugin instance</param>
        internal static void Set(Type type, object obj)
        {
            if (instanceDictionary.ContainsKey(type))
            {
                instanceDictionary[type] = obj;
            }
            else
            {
                instanceDictionary.Add(type, obj);
            }
        }
    }
}
